#include "IO_Connection.hpp"

//解决循环引用问题 -- 头源分离
#include "Reactor_server.hpp"//在源文件里包含就不会导致互相包含问题了

void io_connection::exception_handler()
{
    _server->erase_connection(this->_sockfd_ptr->get_socket_fd());//非法使用
}


void io_connection::send()
{
    std::cout << "进入io_connection::send" << std::endl;
    while(true)
    {
        int send_count = _sockfd_ptr->send(_out_buffer);
        if(send_count > 0) //数据写入内核成功 -- 但不一定全写入了 -- 继续写
        {
            _out_buffer.erase(0, send_count);
            if(_out_buffer.empty() == true) //connection的所有待发送数据都已经写入内核了
                break;

            continue;
        }
        else if(send_count == 0)//对端关闭了
        {
            exception_handler();
            return;//处理完直接return
        }     
        else//send_count < 0
        {
            if(send_count == SEND_DONE)//读完了, 内核buffer已经被写满了, 无法再写入
                break;
            
            else if(send_count == SEND_CONTINUE)
                continue;
            
            else
            {
                LOG(wzx::log_level::ERROR) << "io_connection::receive unknown fail !!!";
                exception_handler();
                return;//处理完直接return
            }
        }
    }
    //出循环只有两种情况: 1. connection的所有待发送数据都已经写入内核了;   2. 内核buffer已经被写满了, 无法再写入
    //为什么要这么处理ET模式下的写事件监视情况? 看png
    if(_out_buffer.empty())//1. connection的所有待发送数据都已经写入内核了
        _server->change_connection_events_IN_and_OUT(_sockfd_ptr->get_socket_fd(), true, false/*让epoll不再监视该fd上的EPOLLOUT*/);
    
    else//2. 内核buffer已经被写满了, 无法再写入
        _server->change_connection_events_IN_and_OUT(_sockfd_ptr->get_socket_fd(), true, true/*让epoll监视该fd上的EPOLLOUT*/);
}